package com.lixinlei.nio2;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousChannelGroup;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Nio2Server {

    private AsynchronousServerSocketChannel assc;

    public void listen() throws IOException {
        //1.创建一个线程池
        ExecutorService es = Executors.newCachedThreadPool();

        //2.创建异步通道群组
        AsynchronousChannelGroup tg = AsynchronousChannelGroup.withCachedThreadPool(es, 1);

        //3.创建服务端异步通道
        AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open(tg);

        //4.绑定监听端口
        assc.bind(new InetSocketAddress(8080));

        //5. 监听连接，传入回调类处理连接请求
        assc.accept(this, new AcceptHandler());
    }

    //具体处理连接请求的就是 completed 方法，它有两个参数：第一个是异步通道，第二个就是上面传入的 NioServer 对象
    private class AcceptHandler implements CompletionHandler<AsynchronousSocketChannel, Nio2Server> {

        @Override
        public void completed(AsynchronousSocketChannel asc, Nio2Server attachment) {
            //调用accept方法继续接收其他客户端的请求
            attachment.assc.accept(attachment, this);

            //1. 先分配好Buffer，告诉内核，数据拷贝到哪里去
            ByteBuffer buf = ByteBuffer.allocate(1024);

            //2. 调用 read 函数读取数据，除了把 buf 作为参数传入，还传入读回调类
            // channel.read(buf, buf, new ReadHandler(asc));
        }

        @Override
        public void failed(Throwable exc, Nio2Server attachment) {

        }

    }

    private class ReadHandler implements CompletionHandler<Integer, ByteBuffer> {

        //读取到消息后的处理
        @Override
        public void completed(Integer result, ByteBuffer attachment) {
            //attachment就是数据，调用flip操作，其实就是把读的位置移动最前面
            attachment.flip();

            //读取数据
            // ...
        }

        @Override
        public void failed(Throwable exc, ByteBuffer attachment) {
            // ...
        }

    }

}
